package designpattern;

/**
 * 单例模式实现
 * 1. 简介
 * 涉及一个单一的类，该类负责自己创建自己，同时需要确保只有单个对象被创建，而且
 * 这个类提供一种访问其对象的方式，可以直接访问不需要实例化该类的对象
 * 主要解决: 一个全局类频繁的创建和销毁
 * 何时使用: 想要控制实例数量，节省系统资源时 - 日志记录器 - 配置管理器
 * 2. 优点
 * (1) 内存只存在一个实例，减少内存的开销
 * (2) 避免对资源的多重占用
 * 3.缺点
 * 没有接口，不能继承与单一职责原则冲突
 * 4.注意
 * (1) 只能存在一个实例
 * (2) 必须自己创建自己的唯一实例
 * (3) 给其它对象提供同一个实例
 * (4) 构造函数私有
 * (5) getInstance()方法需要使用同步锁，防止多线程同时进入造成多实例
 * 5. 常用
 * 一般情况下，不建议使用第 1 种和第 2 种懒汉方式，建议使用第 3 种饿汉方式。
 * 只有在要明确实现 lazy loading 效果时，才会使用第 5 种登记方式。
 * 如果涉及到反序列化创建对象时，可以尝试使用第 6 种枚举方式。
 * 如果有其他特殊的需求，可以考虑使用第 4 种双检锁方式。
 */
public class SingletonTest {
    public static void main(String[] args) {
        Singleton05 instance = Singleton05.getInstance();
        Singleton05 instance2 = Singleton05.getInstance();
        System.out.println(instance == instance2);
    }
}

/**
 * 1. 懒汉式1
 * 使用懒加载，多线程不安全
 */
class Singleton01 {
    private static Singleton01 instance;

    private Singleton01() {
    }

    public static Singleton01 getInstance() {
        if (instance == null) {
            instance = new Singleton01();
        }
        return instance;
    }
}

/**
 * 2. 懒汉式2
 * 懒加载、线程安全
 * 描述: 具备很好的懒加载，在多线程中很好的工作，但是效率较低
 */
class Singleton02 {
    private static Singleton02 instance;

    private Singleton02() {
    }

    public static synchronized Singleton02 getInstance() {
        if (instance == null) {
            instance = new Singleton02();
        }
        return instance;
    }
}

/**
 * 3. 饿汉式
 * 非懒加载，线程安全
 * 描述：比较常用，但是容易产生垃圾对象，未加锁，执行效率护提升，但是在类加载时就初始化浪费内存
 */
class Singleton03 {
    private static Singleton03 instance = new Singleton03();

    private Singleton03() {
    }

    public static Singleton03 getInstance() {
        return instance;
    }

}

/**
 * 4. 双重校验锁
 * 懒加载、线程安全
 * 描述: JDK1.5+,采用双锁机制。在安全的前提下保证高性能
 */
class Singleton04 {
    // 使用 volatile 可以禁止 JVM 的指令重排，保证在多线程环境下也能正常运行(按照程序的步骤走)
    private static volatile Singleton04 instance;

    private Singleton04() {
    }

    public static Singleton04 getInstance() {
        if (instance == null) {
            synchronized (Singleton04.class) {
                if (instance == null) {
                    instance = new Singleton04();
                }
            }
        }
        return instance;
    }
}

/**
 * 5.静态内部类
 */
class Singleton05 {
    private static final Singleton05 instance = new Singleton05();

    private Singleton05() {
    }

    public static Singleton05 getInstance() {
        return instance;
    }
}

/**
 * 6. 枚举类实现
 * 非懒加载，线程安全
 * JDK1.5+,实现单例模式的最佳方式,防止反序列化重新创建新的对象，绝对防止多次实例化
 */
enum Singleton06 {
    INSTANCT;

    public int testMethod() {
        return 1;
    }
}